package com.xishu.service.order.front.query;

import com.xishu.config.Config;
import com.xishu.config.ContextConstant;
import com.xishu.entity.User;
import com.xishu.entity.order.Order;
import com.xishu.entity.order.OrderItem;
import com.xishu.entity.plat.GlobalSetting;
import com.xishu.entity.shop.DiscountTicket;
import com.xishu.entity.shop.Reason;
import com.xishu.entity.shop.Shop;
import com.xishu.response.ResponseData;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.service.order.base.OrderService;
import com.xishu.upgrade.UpgradeOrderService;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.impl.ChainBase;
import org.apache.commons.chain.impl.ContextBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.*;
import static com.xishu.config.Constant.USER_SELECT_PAY_TYPE_PART_FOOD;

/**
 * 前端订单查询
 */
public class QueryOrderChain extends ChainBase {
    private static Logger logger = LoggerFactory.getLogger(QueryOrderChain.class);
    private CommonService commonService = CommonService.getInstance();

    public QueryOrderChain() {
        addCommand(new DefaultValueCmd());
        addCommand(new VerifyCmd());
        addCommand(new DefaultTableOrderCmd());
        addCommand(new QueryCmd());
    }

    public ResponseData queryOrder(Order order) throws Exception {
        QueryOrderChain chain = new QueryOrderChain();
        Context context = new ContextBase();
        context.put(ContextConstant.CONTEXT_ORDER, order);
        chain.execute(context);

        ResponseData responseData = (ResponseData) context.get(ContextConstant.CONTEXT_RESULT);

        return responseData;
    }

}

class DefaultValueCmd implements Command, Tools {
    private OrderService orderService = OrderService.getInstance();

    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        order.setSortField(new String[]{"createTime"});
        order.setSortType("DESC");

        orderService.payTypeListToBitPayType(order);

        boolean bEndRequest = ServletUtil.getUserId() != null;

        Long userId = ServletUtil.getUserId();

        //查询经营时的订单
        if (getBoolean(order.getBusinessEndShow()) && userId != null) {
            Long shopId = order.getShopId();
            Shop shop = ShopService.getInstance().findShopById(shopId);
            order.setStartCreateTime(shop.getOpenTime());
        } else if (getBoolean(order.getExpiredOrder()) && userId != null) {
            Long shopId = order.getShopId();
            Shop shop = ShopService.getInstance().findShopById(shopId);
            order.setStartCreateTime(shop.getOpenTime());
        }

        context.put(ContextConstant.BE_REQUEST, bEndRequest);

        return false;
    }
}

class VerifyCmd implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(VerifyCmd.class);
    private OrderService orderService = OrderService.getInstance();
    private CommonService commonService = CommonService.getInstance();

    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);

        Order parentOrder = commonService.searchOne(order);

        Long userId = ServletUtil.getUserId();
        Long shopId = order.getShopId();
        Long companyId = order.getCompanyId();
        Long parentOrderId = order.getParentOrderId();
        VerifyUtil.verify(() -> shopId != null || companyId != null || parentOrderId != null);

        //如果是没有登录的账号，那么只能查询开店之后的订单
        if (shopId != null) {
            Shop shop = ShopService.getInstance().findShopById(shopId);
            if (userId == null) {
                logger.info("add shop open time {}", shop.getOpenTime());

                //C端登录用户不设该限制
                if (parentOrder != null && !equals(parentOrder.getCustomerId(), ServletUtil.getCustomerId())) {
                    order.setStartCreateTime(shop.getOpenTime());
                }
                //C端账号，只能查询ID,电话号码，或者foodTableKey
                //也就是限制查询订单的数量
                VerifyUtil.verify(() -> order.getId() != null || isNotEmpty(order.getContact())
                        || isNotEmpty(order.getPhone()) || isNotEmpty(order.getFoodTableKey())
                        || order.getUniqueCode() != null);

                return false;
            }

            User user = ServletUtil.getUser();
            boolean ownCompany = CompanyService.getInstance().ownCompany(user, shop.getCompanyId());
            VerifyUtil.verify(() -> ownCompany);

            return false;
        }

        //这里的订单只能是VIP订单
        Order orderInDb = orderService.findOrder(order.id);
        if (!getBoolean(orderInDb.getVipOrder())) {
            context.put(ContextConstant.CONTEXT_RESULT, commonService.createResponse(new ArrayList<>()));
            logger.info("order not valid query");
            return true;
        }

        return false;
    }
}

/**
 * 固定二维码订单处理
 */
class DefaultTableOrderCmd implements Command {
    private OrderService orderService = OrderService.getInstance();

    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        GlobalSetting globalSetting = GlobalService.getInstance().getGlobalSetting();
        context.put(ContextConstant.GLOBAL_SETTING, globalSetting);

        //如果是固定餐桌的订单，那么先查询是否存在，如果不存在，先创建一个
        if (order.getUniqueCode() != null && order.getUniqueCode() == 0) {
            VerifyUtil.verify(() -> order.getTableRow() != null);
            VerifyUtil.verify(() -> order.getTableColumn() != null);
            Order fixOrder = orderService.searchFixOrder(order.getShopId(), order.getTableRow(), order.getTableColumn(), globalSetting);
            if (fixOrder == null) {
                //创建新的订单
                orderService.createFixOrder(order.getShopId(), order.getTableRow(), order.getTableColumn());
            }
        }

        return false;
    }
}

class QueryCmd implements Command, Tools {
    private static Logger logger = LoggerFactory.getLogger(QueryCmd.class);
    private CommonService commonService = CommonService.getInstance();
    private OrderService orderService = OrderService.getInstance();


    @Override
    public boolean execute(Context context) throws Exception {
        Order order = (Order) context.get(ContextConstant.CONTEXT_ORDER);
        GlobalSetting globalSetting = (GlobalSetting) context.get(ContextConstant.GLOBAL_SETTING);
        boolean bEndRequest = (Boolean) context.get(ContextConstant.BE_REQUEST);

        ResponseData responseData = commonService.searchResponse(order, orderInDb -> {
            //升级支付方式
            UpgradeOrderService.getInstance().upgradePayTypeBit(orderInDb);
            UpgradeOrderService.getInstance().upgradeCashPay(orderInDb);
            UpgradeOrderService.getInstance().upgradePayTypeName(orderInDb);

            //处理是否可以显示
            orderService.dealCustomerShow(orderInDb, globalSetting);

            orderService.showPrice(orderInDb, bEndRequest);

            List<Integer> payTypeList = getPayTypeList(orderInDb);

            orderInDb.setPayTypeList(payTypeList);
            orderInDb.setUserCostLong(showMoneyDouble(getDouble(orderInDb.getUserCost()) * 100).longValue());

            //如果是外卖订单，直接成外卖
            if (getInt(orderInDb.getOrderType()) == ORDER_TYPE_TAKE_OUT || getInt(orderInDb.getOrderType()) == ORDER_TYPE_TAKE_OUT_PLAT) {
                for (OrderItem orderItem : getList(orderInDb.getOrderItemDetailList())) {
                    orderItem.setTakeout(true);
                }
            }

            if (getInt(orderInDb.getStatus()) != ORDER_STATUS_END && getInt(orderInDb.getUserSelectPayType()) != USER_SELECT_PAY_TYPE_PART_FOOD) {
                //规避方案，如果未支付金额跟订单金额一样，那么清空支付方式
                double orderPayed = getDouble(orderInDb.getLeftCash()) - getDouble(orderInDb.getUserCost());

                if (showMoneyDouble(orderPayed) == 0) {
                    orderInDb.setPayTypeList(new ArrayList<>());
                }
            }

            //请求里面需要过滤出来
            if (getBoolean(order.getFilterCheckoutOrderItem())) {
                logger.info("will filter checkout  order item");
                orderService.filterCheckoutOrderItem(orderInDb);
            }

            //需要查询具体的优惠卷
            if (getBoolean(order.getShowTicket())) {
                List<String> ticketCodeList = DiscountTicketService.getInstance().getAllTicket(orderInDb);

                try {
                    Shop ticketForShop = ShopService.getInstance().findShopById(orderInDb.getShopId());
                    List<DiscountTicket> ticketList = ticketCodeList.stream().map(code -> {
                        Optional<DiscountTicket> discountTicketOptional = DiscountTicketService.getInstance().findTicket(code, ticketForShop.getCompanyId());
                        if (discountTicketOptional.isPresent()) {
                            return discountTicketOptional.get();
                        } else {
                            return null;
                        }

                    }).filter(p -> p != null).collect(Collectors.toList());

                    orderInDb.setTicketList(ticketList);
                } catch (Exception e) {
                    logger.error("er", e);
                }
            }

            //如果要查询退款理由
            if (getBoolean(order.getShowReason())) {
                List<Reason> reasonList = orderService.findReason(orderInDb.getShopId(), orderInDb.getId());
                orderInDb.setReasonList(reasonList);
            }

            //如果要查询分店的名称
            if (getBoolean(order.getQueryShopName())) {
                try {
                    Shop shopForName = ShopService.getInstance().findShopById(orderInDb.getShopId());
                    ShopService shopService = ShopService.getInstance();
                    orderInDb.setShopName_zh(shopService.getShopNameZh(shopForName));
                    orderInDb.setShopName_en(shopService.getShopNameEn(shopForName));
                } catch (Exception e) {
                    logger.error("e", e);
                }
            }
        }, orderList -> {
            if (isEmpty(orderList)) {
                return orderList;
            }
            //处理店铺中英文名称是null
            for (Order orderInDb : orderList) {
                if (isNotEmpty(orderInDb.getShopName())) {
                    if (isEmpty(orderInDb.getShopName_zh())) {
                        orderInDb.setShopName_zh(orderInDb.getShopName());
                    }
                    if (isEmpty(orderInDb.getShopName_en())) {
                        orderInDb.setShopName_en(orderInDb.getShopName());
                    }
                }
            }


            //B端用户不受影响
            if (ServletUtil.getUserId() != null) {
                return orderList;
            }
            //被合并的订单c端二维码失效
            orderList = orderList.stream().filter((o) -> !getBoolean(o.getCombineOrder())).collect(Collectors.toList());

            if (order.getUniqueCode() == null && isEmpty(order.getFoodTableKey())) {
                //显示没有关闭的订单
                return filterNoCloseOrder(orderList);
            }

            //以下是为了处理订单完成之后，什么时候失效的问题

            //传了food table key，但是没有传unique code
            if (isNotEmpty(order.getFoodTableKey()) && order.getUniqueCode() == null) {
                String[] split = order.getFoodTableKey().split(":");
                if (split.length == 3) {
                    order.setUniqueCode(Integer.parseInt(split[2]));
                }
            }

            try {
                Shop shopInDb = ShopService.getInstance().findShopById(orderList.get(0).getShopId());

                //即时订单，也需要单独处理
                if (getInt(order.getUniqueCode()) != 0) {
                    return filterNoCloseOrder(filterQrCodeOrderList(orderList, shopInDb));
                }

                //如果是订单的unique code为0需要单独处理
                return filterNoCloseOrder(filterDeskOrderList(orderList, shopInDb));
            } catch (Exception e) {
                logger.error("e", e);
                return new ArrayList<>();
            }
        });

        context.put(ContextConstant.CONTEXT_RESULT, responseData);

        return false;
    }

    /**
     * 获取支付类型
     *
     * @param orderInDb
     * @return
     */
    private List<Integer> getPayTypeList(Order orderInDb) {
        List<Integer> payTypeList = bitNumberToIntList(orderInDb.getPayTypeBit());
        return payTypeList;
    }

    /**
     * 过滤没有关闭的订单
     *
     * @param orderList
     * @return
     */
    private List<Order> filterNoCloseOrder(List<Order> orderList) {
        return getList(orderList).stream().filter(p -> !getBoolean(p.getClose())).collect(Collectors.toList());
    }

    /**
     * 过滤
     *
     * @param orderList
     * @param shopInDb
     * @return
     */
    private List<Order> filterQrCodeOrderList(List<Order> orderList, Shop shopInDb) {
        logger.info("filterQrCodeOrderList");
        Order orderInDb = orderList.get(0);

        //没有付款的订单，直接返回
        if (!getBoolean(orderInDb.getPayed())) {
            return orderList;
        }

        if (getBoolean(orderInDb.getPayFirst())) {
            if (shopInDb.getQrCodeDisableAddNewOrderPayFirst() == null) {
                shopInDb.setQrCodeDisableAddNewOrderPayFirst(Config.getInstance().qrCodeDisableAddNewOrderPayFirst());
            }

            int expireTime = getInt(shopInDb.getQrCodeDisableAddNewOrderPayFirst()) * 60 * 1000;

            //默认30秒过期
            if (expireTime == 0) {
                expireTime = 30 * 1000;
            }

            //有具体的时间
            if (System.currentTimeMillis() - getLong(orderInDb.getPayEndTime()) > expireTime) {
                return new ArrayList<>();
            }

            //没有超时，原样返回
            return orderList;
        } else {
            //后付款
            int expireTime = getInt(shopInDb.getQrCodeDisableAddNewOrderPayAfter()) * 60 * 1000;

            if (expireTime == 0) {
                expireTime = 30 * 1000;
            }

            //有具体的时间
            if (System.currentTimeMillis() - getLong(orderInDb.getPayEndTime()) > expireTime) {
                return new ArrayList<>();
            }

            //没有超时，原样返回
            return orderList;
        }
    }

    /**
     * 查询餐桌固定订单
     *
     * @param orderList
     * @param shopInDb
     * @return
     */
    private List<Order> filterDeskOrderList(List<Order> orderList, Shop shopInDb) {
        logger.info("filterDeskOrderList");
        Order orderInDb = orderList.get(0);

        //没有付款的订单，直接返回
        if (!getBoolean(orderInDb.getPayed())) {
            return orderList;
        }

        if (getBoolean(orderInDb.getPayFirst())) {
            int expireTime = getInt(shopInDb.getQrCodeOnDeskDisablePayFirst()) * 60 * 1000;

            if (expireTime == 0) {
                expireTime = 30 * 1000;
            }

            //有具体的时间
            if (System.currentTimeMillis() - getLong(orderInDb.getPayEndTime()) > expireTime) {
                return new ArrayList<>();
            }

            //没有超时，原样返回
            return orderList;
        } else {
            int expireTime = getInt(shopInDb.getQrCodeOnDeskDisablePayAfter()) * 60 * 1000;

            if (expireTime == 0) {
                expireTime = 30 * 1000;
            }

            //有具体的时间
            if (System.currentTimeMillis() - getLong(orderInDb.getPayEndTime()) > expireTime) {
                return new ArrayList<>();
            }

            //没有超时，原样返回
            return orderList;
        }
    }
}

